package com.yochi.pictureseditor.factories;

import com.yochi.pictureseditor.effects.ColorEnum;
import com.yochi.pictureseditor.effects.Effect;
import com.yochi.pictureseditor.effects.EffectEnum;
import com.yochi.pictureseditor.effects.EffectSequential;
import com.yochi.pictureseditor.effects.effectsimpl.EffectAddBWNoize;
import com.yochi.pictureseditor.effects.effectsimpl.EffectAddNoize;
import com.yochi.pictureseditor.effects.effectsimpl.EffectAdjustBrightness;
import com.yochi.pictureseditor.effects.effectsimpl.EffectAdjustContrast;
import com.yochi.pictureseditor.effects.effectsimpl.EffectAdjustGamma;
import com.yochi.pictureseditor.effects.effectsimpl.EffectAdjustHue;
import com.yochi.pictureseditor.effects.effectsimpl.EffectAdjustTransparency;
import com.yochi.pictureseditor.effects.effectsimpl.EffectAverage;
import com.yochi.pictureseditor.effects.effectsimpl.EffectBichrome;
import com.yochi.pictureseditor.effects.effectsimpl.EffectBlackAndWhite;
import com.yochi.pictureseditor.effects.effectsimpl.EffectBlur;
import com.yochi.pictureseditor.effects.effectsimpl.EffectCanvas;
import com.yochi.pictureseditor.effects.effectsimpl.EffectColorize;
import com.yochi.pictureseditor.effects.effectsimpl.EffectColorizedMozaic1;
import com.yochi.pictureseditor.effects.effectsimpl.EffectColorizedMozaic2;
import com.yochi.pictureseditor.effects.effectsimpl.EffectContrastBooster;
import com.yochi.pictureseditor.effects.effectsimpl.EffectCustomRotation;
import com.yochi.pictureseditor.effects.effectsimpl.EffectCutter;
import com.yochi.pictureseditor.effects.effectsimpl.EffectDrawing;
import com.yochi.pictureseditor.effects.effectsimpl.EffectFilter;
import com.yochi.pictureseditor.effects.effectsimpl.EffectGradientMozaic;
import com.yochi.pictureseditor.effects.effectsimpl.EffectHorizontalMirror;
import com.yochi.pictureseditor.effects.effectsimpl.EffectInShape;
import com.yochi.pictureseditor.effects.effectsimpl.EffectMonochrome;
import com.yochi.pictureseditor.effects.effectsimpl.EffectOctochrome;
import com.yochi.pictureseditor.effects.effectsimpl.EffectPastel;
import com.yochi.pictureseditor.effects.effectsimpl.EffectPetrol;
import com.yochi.pictureseditor.effects.effectsimpl.EffectPixelize;
import com.yochi.pictureseditor.effects.effectsimpl.EffectReverseColors;
import com.yochi.pictureseditor.effects.effectsimpl.EffectRotation;
import com.yochi.pictureseditor.effects.effectsimpl.EffectSepia;
import com.yochi.pictureseditor.effects.effectsimpl.EffectShadow;
import com.yochi.pictureseditor.effects.effectsimpl.EffectSimpleMozaic;
import com.yochi.pictureseditor.effects.effectsimpl.EffectSobel;
import com.yochi.pictureseditor.effects.effectsimpl.EffectSpectrumCorrection;
import com.yochi.pictureseditor.effects.effectsimpl.EffectSpirals;
import com.yochi.pictureseditor.effects.effectsimpl.EffectVerticalMirror;
import com.yochi.pictureseditor.effects.effectsimpl.EffectWaves;
import com.yochi.pictureseditor.effects.filters.Filter;
import com.yochi.pictureseditor.effects.filters.FilterEnum;
import com.yochi.pictureseditor.effects.filters.filtersimpl.FilterEdgeDetection;
import com.yochi.pictureseditor.effects.filters.filtersimpl.FilterEmbossing;
import com.yochi.pictureseditor.effects.filters.filtersimpl.FilterRelief;
import com.yochi.pictureseditor.effects.filters.filtersimpl.FilterShine;
import com.yochi.pictureseditor.effects.filters.filtersimpl.FilterSobel1;
import com.yochi.pictureseditor.effects.filters.filtersimpl.FilterSobel2;
import com.yochi.pictureseditor.effects.filters.filtersimpl.FilterSurex;
import com.yochi.pictureseditor.effects.shapes.ShapeCircle;
import com.yochi.pictureseditor.effects.shapes.ShapeRectangle;
import com.yochi.pictureseditor.exceptions.EffectNotCreatedException;
import com.yochi.pictureseditor.exceptions.NullImageException;
import com.yochi.pictureseditor.images.Image;
import com.yochi.pictureseditor.tools.Color;

public class EffectFactory implements EffectFactoryInterface {
	
	public Effect build(Image image, EffectEnum effect, FilterEnum filterEnum, 
					ColorEnum color, Color color1, Color color2, Filter filter, int parameter, int p1, int p2, int p3)
					throws NullImageException, EffectNotCreatedException {
		
		// if effect to apply match with an EffectEnum and needs no parameter or int parameter(s)
		if(filterEnum == null && color == null && effect != null && color1 == null && color2 == null) {
			// if effect needs one parameter (or no parameter)
			if(p1==-1 && p2==-1 && p3==-1) {
				return buildEffect(effect, image, parameter);
			// if effect needs two parameters
			} else if(p1!=-1 && p2!=-1 && p3==-1) {
				return buildEffect(effect, image, p1, p2); 
			// if effect needs three parameters
			} else {
				return buildEffect(effect, image, p1, p2, p3);
			}

		// if effect to apply match with an EffectEnum and needs two colors parameter
		} else if(filterEnum == null && color == null && effect != null && color1 != null && color2 != null) {
			return buildEffect(effect, image, parameter, color1, color2);

		// if effect to apply match with an EffectEnum and needs one color parameter
		} else if(filterEnum == null && color != null && effect != null) {
			// if color is passed as int parameters
			if(color.equals(ColorEnum.PERSONALIZED)) {
				return buildEffect(effect, image, p1, p2, p3);
			// if color is passed as Color parameter
			} else {
				return buildEffect(effect, image, color);
			}

		// if effect to apply match with a FilterEnum
		} else if(filterEnum!=null && color==null && effect==null) {
			// if filter should be personalized
			if(filterEnum.equals(FilterEnum.PERSONALIZED)) {
				return buildEffect(filter, image);
			// if filter is pre-loaded
			} else {
				return buildEffect(filterEnum, image);
			}
		}
		
		throw new EffectNotCreatedException("can't find creator method");
	}

	
	public Effect buildEffect(EffectEnum type, Image image) throws NullImageException {
		if(image==null) throw new NullImageException("effect can't be apply on null image");
		Effect effect = null;
		int parameter = 0;
		switch(type) {
		    case ADDNOIZE:
		    	effect = new EffectAddNoize(image, parameter); 
				break;
		    case ADJUST_BRIGHTNESS:
		    	effect = new EffectAdjustBrightness(image, parameter); 
				break;
		    case ADJUST_CONTRAST:
		    	effect = new EffectAdjustContrast(image, parameter); 
				break;
		    case ADJUST_HUE:
		    	effect = new EffectAdjustHue(image, parameter);
		    	break;
		    case ADJUST_GAMMA:
		    	effect = new EffectAdjustGamma(image, parameter); 
				break;
		    case ADJUST_TRANSPARENCY:
		    	effect = new EffectAdjustTransparency(image, parameter); 
				break;
		    case ADDBWNOIZE:
		    	effect = new EffectAddBWNoize(image, parameter);
				break;
			case BLUR:
				effect = new EffectBlur(image, parameter); 
				break;
			case PIXELIZE:
				effect = new EffectCanvas(image, parameter); 
				break;
			case MONOCHROME:
				effect = new EffectMonochrome(image, parameter); 
				break;
			case OCTOCHROME:
				effect = new EffectOctochrome(image, parameter); 
				break;
			case CUSTOM_ROTATION:
				effect = new EffectCustomRotation(image, parameter); 
				break;
			case BICHROME:
				effect = new EffectBichrome(image, parameter, new Color((char)0,(char)0,(char)0), new Color((char)255,(char)255,(char)255)); 
				break;
			case CANVAS:
				effect = new EffectCanvas(image, parameter); 
				break;
			case SEPIA:
				effect = new EffectSepia(image); break;
			case PETROL:
				effect = new EffectPetrol(image); break;
			case AVERAGE:
				effect = new EffectAverage(image); break;
			case SPECTRUM:
				effect = new EffectSpectrumCorrection(image); break;
			case SOBEL:
				effect = new EffectSobel(image); break;
			case PASTEL:
				effect = new EffectPastel(image); break;
			case DRAWING:
				effect = new EffectDrawing(image); break;
			case CUTTER:
				effect = new EffectCutter(image, false); break;
			case SIMPLEMOZAIC:
				effect = new EffectSimpleMozaic(image); break;
			case COLORIZEDMOZAIC1:
				effect = new EffectColorizedMozaic1(image); break;
			case COLORIZEDMOZAIC2:
				effect = new EffectColorizedMozaic2(image); break;
			case GRADIENTMOZAIC:
				effect = new EffectGradientMozaic(image); break;
			case INCIRCLE:
				effect = new EffectInShape(image, new ShapeCircle()); break;
			case INRECTANGLE:
				effect = new EffectInShape(image, new ShapeRectangle()); break;
			case REVERSECOLOR:
				effect = new EffectReverseColors(image); break;
			case BLACKANDWHITE:
				effect = new EffectBlackAndWhite(image); break;
			case CONTRAST_BOOSTER:
				effect = new EffectContrastBooster(image); break;
			case SEQUENTIAL:
				effect = new EffectSequential(image); break;
			case ROTATION:
				effect = new EffectRotation(image); break;
			case VERTICALMIRROR:
				effect = new EffectVerticalMirror(image); break;
			case HORIZONTALMIRROR:
				effect = new EffectHorizontalMirror(image); break;
			case SHADOW:
				effect = new EffectShadow(image); break;
			default:
				break;
		}
		return effect;
	}

	public Effect buildEffect(EffectEnum type, Image image, int param) throws NullImageException {
		if(image==null) throw new NullImageException("effect can't be apply on null image");
		Effect effect = null;
		switch(type) {
		case ADDNOIZE:
			effect = new EffectAddNoize(image, param); break;
	    case ADJUST_BRIGHTNESS:
	    	effect = new EffectAdjustBrightness(image, param); break;
	    case ADJUST_HUE:
	    	effect = new EffectAdjustHue(image, param); break;
	    case ADJUST_CONTRAST:
	    	effect = new EffectAdjustContrast(image, param); break;
	    case ADJUST_GAMMA:
	    	effect = new EffectAdjustGamma(image, param); break; 
	    case ADJUST_TRANSPARENCY:
	    	effect = new EffectAdjustTransparency(image, param);  break;
		case ADDBWNOIZE:
			effect = new EffectAddBWNoize(image, param); break;
		case BLUR:
			effect = new EffectBlur(image, param); break;
		case PIXELIZE:
			effect = new EffectPixelize(image, param); break;
		case CANVAS:
			effect = new EffectCanvas(image, param); break;
		case MONOCHROME:
			effect = new EffectMonochrome(image, param); break;
		case CUSTOM_ROTATION:
			effect = new EffectCustomRotation(image, param); break;
		case BICHROME:
			effect = new EffectBichrome(image, param, new Color((char)0,(char)0,(char)0), new Color((char)255, (char)255, (char)255));  break;
		case OCTOCHROME:
			effect = new EffectOctochrome(image, param); break;
		default:
			effect = buildEffect(type, image); break;
		}
		return effect;
	}
	
	public Effect buildEffect(EffectEnum type, Image image, ColorEnum color) throws NullImageException {
		if(image==null) throw new NullImageException("effect can't be apply on null image");
		Effect effect = null;
		switch(type) {
		case COLORIZE:
			effect = new EffectColorize(image, color); break;
		default:
			buildEffect(type, image); break;
		}
		return effect;
	}
	
	public Effect buildEffect(EffectEnum type, Image image, int p1, int p2) throws NullImageException {
		if(image==null) throw new NullImageException("effect can't be apply on null image");
		Effect effect = null;
		switch(type) {
		case SPIRALS:
			effect = new EffectSpirals(image, p1, p2); break;
		default:
			buildEffect(type, image); break;
		}
		return effect;
	}
	
	public Effect buildEffect(EffectEnum type, Image image, int p1, int p2, int p3) throws NullImageException {
		if(image==null) throw new NullImageException("effect can't be apply on null image");
		Effect effect = null;
		switch(type) {
		case COLORIZE:
			effect = new EffectColorize(image, p1, p2, p3); break;
		case WAVES:
			effect = new EffectWaves(image, p1, p2, p3); break;
		default:
			buildEffect(type, image); break;
		}
		return effect;
	}
	
	public Effect buildEffect(EffectEnum type, Image image, int parameter, Color color1, Color color2) throws NullImageException {
		if(image==null) throw new NullImageException("effect can't be apply on null image");
		Effect effect = null;
		switch(type) {
		case BICHROME:
			effect = new EffectBichrome(image, parameter, color1, color2); break;
		default:
			buildEffect(type, image); break;
		}
		return effect;
	}
	
	public Effect buildEffect(EffectEnum type, Image image, boolean preview) throws NullImageException {
		if(image==null) throw new NullImageException("effect can't be apply on null image");
		Effect effect = null;
		switch(type) {
		case CUTTER:
			effect = new EffectCutter(image, preview); break;
		default:
			buildEffect(type, image); break;
		}
		return effect;
	}

	public EffectFilter buildEffect(FilterEnum type, Image image)  throws NullImageException {
		if(image==null) throw new NullImageException("effect can't be apply on null image");
		EffectFilter effect = null;
		switch(type) {
			case EDGEDETECTION:
				effect = new EffectFilter(image, new FilterEdgeDetection()); break;
			case EMBOSSING:
				effect = new EffectFilter(image, new FilterEmbossing()); break;
			case SHINE:
				effect = new EffectFilter(image, new FilterShine()); break;
			case RELIEF:
				effect = new EffectFilter(image, new FilterRelief()); break;
			case SUREX:
				effect = new EffectFilter(image, new FilterSurex()); break;
			case SOBEL1:
				effect = new EffectFilter(image, new FilterSobel1()); break;
			case SOBEL2:
				effect = new EffectFilter(image, new FilterSobel2()); break;
			default: break;
		}
		return effect;
	}

	public Effect buildEffect(Filter type, Image image) throws NullImageException {
		if(image==null) throw new NullImageException("effect can't be apply on null image");
		return new EffectFilter(image, type);
	}

}
